﻿using System;
using System.Net;

namespace HashFoo.Core
{
    /// <summary>
    /// A web client operation token.
    /// </summary>
    /// <see cref="IWebClientOperation"/>
    public class WebRequestClientOperation : IWebClientOperation
    {
        readonly Action _cancelCallback;

        readonly object _syncLock = new object();

        /// <summary>
        /// The <see cref="HttpWebRequest"/> the operation is linked to.
        /// </summary>
        public HttpWebRequest Request { get; private set; }

        /// <summary>
        /// Create a new <see cref="WebRequestClientOperation"/> for a web request.
        /// </summary>
        /// <param name="webRequest"></param>
        /// <param name="cancelCallback"></param>
        public WebRequestClientOperation(HttpWebRequest webRequest, Action cancelCallback = null)
        {
            Request = webRequest;
            _cancelCallback = cancelCallback;
        }

        /// <summary>
        /// Marks an operation as complete and executes an optional callback if the operation has not been previously canceled.
        /// </summary>
        /// <param name="callback"></param>
        public void MarkAsComplete(Action callback = null)
        {
            lock (_syncLock)
            {
                if (Request == null) return;

                if (callback != null) callback();
                Request = null;
                OnCompleted();
            }
        }

        /// <summary>
        /// Cancels a web client operation.
        /// </summary>
        public void Cancel()
        {
            lock (_syncLock)
            {
                if (Request == null) return;

                if (_cancelCallback != null) _cancelCallback();
                Request = null;
                OnCompleted();
            }
        }

        /// <summary>
        /// True if the operation is no longer active.  If true, it does not necessarily mean
        /// the operation was completed successfully, just that its done.
        /// </summary>
        public bool IsDone
        {
            get
            {
                lock (_syncLock)
                {
                    // an operation is completed if the request is null.
                    return (Request == null);
                }
            }
        }

        /// <summary>
        /// Raised when the operation is completed (could be error, cancel, or success).
        /// </summary>
        public event Action Completed;

        void OnCompleted()
        {
            var handler = Completed;
            if (handler != null) handler();
        }
    }
}